// 发布订阅模式

export default class EventEmitter {
  constructor () {
    // { eventType: [ handler1，handler2 ]}
    this.subs = {}
  }

  // 订阅通知, 可以注册多个事件
  $on (eventType, handler) {
    // 判断有没有, 如果有赋值,没有赋值[]
    // 将方法缓存
    (this.subs[eventType] || (this.subs[eventType] = [])).push(handler)
  }

  // 发布通知
  $emit (eventType, data) {
    if (this.subs[eventType]) {
      this.subs[eventType].forEach(handler => { // 循环调用存储的方法
        handler(data)
      })
    }
  }

  // 监听一次
  $once (eventType, handler) {
    // 先绑定，调用后删除
    const _this = this
    function on () {
      _this.$off(eventType, on)
      handler.apply(_this, arguments)
    }
    on.fn = handler
    this.$on(eventType, on)
  }

  // 取消
  $off (eventType, handler) {
    const sub = this.subs[eventType]

    if (!sub) return false

    if (!handler) {
      // 如果没有传 handler 的话，就会将 eventType 值对应缓存列表中的 handler 都清空
      sub && (sub.length = 0)
    } else {
      for (let i = 0; i < sub.length; i++) {
        if (sub[i] === handler || sub[i].fn === handler) {
          sub.splice(i, 1)
          break
        }
      }
    }
  }
}
